package com.wkh.project.customer.service.impl;

import com.wkh.project.common.result.Result;
import com.wkh.project.common.result.ResultCodeEnum;
import com.wkh.project.customer.client.CustomerInfoFeignClient;
import com.wkh.project.customer.service.OrderService;
import com.wkh.project.dispatch.client.NewOrderFeignClient;
import com.wkh.project.driver.client.DriverInfoFeignClient;
import com.wkh.project.map.client.LocationFeignClient;
import com.wkh.project.map.client.MapFeignClient;
import com.wkh.project.map.client.WxPayFeignClient;
import com.wkh.project.model.entity.order.OrderInfo;
import com.wkh.project.model.enums.OrderStatus;
import com.wkh.project.model.form.customer.ExpectOrderForm;
import com.wkh.project.model.form.customer.SubmitOrderForm;
import com.wkh.project.model.form.map.CalculateDrivingLineForm;
import com.wkh.project.model.form.map.SearchNearByDriverForm;
import com.wkh.project.model.form.order.OrderInfoForm;
import com.wkh.project.model.form.payment.CreateWxPaymentForm;
import com.wkh.project.model.form.payment.PaymentInfoForm;
import com.wkh.project.model.form.rules.FeeRuleRequestForm;
import com.wkh.project.model.vo.base.PageVo;
import com.wkh.project.model.vo.customer.ExpectOrderVo;
import com.wkh.project.model.vo.dispatch.NewOrderTaskVo;
import com.wkh.project.model.vo.driver.DriverInfoVo;
import com.wkh.project.model.vo.map.DrivingLineVo;
import com.wkh.project.model.vo.map.NearByDriverVo;
import com.wkh.project.model.vo.map.OrderLocationVo;
import com.wkh.project.model.vo.map.OrderServiceLastLocationVo;
import com.wkh.project.model.vo.order.*;
import com.wkh.project.model.vo.payment.WxPrepayVo;
import com.wkh.project.model.vo.rules.FeeRuleResponseVo;
import com.wkh.project.order.client.OrderInfoFeignClient;
import com.wkh.project.rules.client.FeeRuleFeignClient;
import com.wkh.project.service.execption.GuiguException;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class OrderServiceImpl implements OrderService {

    @Resource
    private MapFeignClient mapFeignClient;

    @Resource
    private FeeRuleFeignClient feeRuleFeignClient;

    @Resource
    private OrderInfoFeignClient orderInfoFeignClient;

    @Resource
    private NewOrderFeignClient newOrderFeignClient;

    @Resource
    private DriverInfoFeignClient driverInfoFeignClient;

    @Resource
    private LocationFeignClient locationFeignClient;
    @Resource
    private WxPayFeignClient wxPayFeignClient;
    @Autowired
    private CustomerInfoFeignClient customerInfoFeignClient;

    @Override
    public ExpectOrderVo expectOrder(ExpectOrderForm expectOrderForm) {
        //计算驾驶线路
        CalculateDrivingLineForm calculateDrivingLineForm = new CalculateDrivingLineForm();
        BeanUtils.copyProperties(expectOrderForm, calculateDrivingLineForm);
        DrivingLineVo drivingLineVo = mapFeignClient.calculateDrivingLine(calculateDrivingLineForm).getData();

        //计算订单费用
        FeeRuleRequestForm calculateOrderFeeForm = new FeeRuleRequestForm();
        calculateOrderFeeForm.setDistance(drivingLineVo.getDistance());
        calculateOrderFeeForm.setStartTime(new Date());
        calculateOrderFeeForm.setWaitMinute(0);
        FeeRuleResponseVo feeRuleResponseVo = feeRuleFeignClient.calculateOrderFee(calculateOrderFeeForm).getData();

        //预估订单实体
        ExpectOrderVo expectOrderVo = new ExpectOrderVo();
        expectOrderVo.setDrivingLineVo(drivingLineVo);
        expectOrderVo.setFeeRuleResponseVo(feeRuleResponseVo);
        return expectOrderVo;
    }

    @Override
    public Long submitOrder(SubmitOrderForm submitOrderForm) {
        //1.重新计算驾驶线路
        CalculateDrivingLineForm calculateDrivingLineForm = new CalculateDrivingLineForm();
        BeanUtils.copyProperties(submitOrderForm, calculateDrivingLineForm);
        DrivingLineVo drivingLineVo = mapFeignClient.calculateDrivingLine(calculateDrivingLineForm).getData();

        //2.重新计算订单费用
        FeeRuleRequestForm calculateOrderFeeForm = new FeeRuleRequestForm();
        calculateOrderFeeForm.setDistance(drivingLineVo.getDistance());
        calculateOrderFeeForm.setStartTime(new Date());
        calculateOrderFeeForm.setWaitMinute(0);
        FeeRuleResponseVo feeRuleResponseVo = feeRuleFeignClient.calculateOrderFee(calculateOrderFeeForm).getData();

        //3.封装订单信息对象
        OrderInfoForm orderInfoForm = new OrderInfoForm();
        //订单位置信息
        BeanUtils.copyProperties(submitOrderForm, orderInfoForm);
        //预估里程
        orderInfoForm.setExpectDistance(drivingLineVo.getDistance());
        orderInfoForm.setExpectAmount(feeRuleResponseVo.getTotalAmount());

        //4.保存订单信息
        Long orderId = orderInfoFeignClient.saveOrderInfo(orderInfoForm).getData();

        //查询附近可以接单的司机
        //5.1.封装调度参数对象
        NewOrderTaskVo newOrderDispatchVo = new NewOrderTaskVo();
        newOrderDispatchVo.setOrderId(orderId);
        newOrderDispatchVo.setStartLocation(orderInfoForm.getStartLocation());
        newOrderDispatchVo.setStartPointLongitude(orderInfoForm.getStartPointLongitude());
        newOrderDispatchVo.setStartPointLatitude(orderInfoForm.getStartPointLatitude());
        newOrderDispatchVo.setEndLocation(orderInfoForm.getEndLocation());
        newOrderDispatchVo.setEndPointLongitude(orderInfoForm.getEndPointLongitude());
        newOrderDispatchVo.setEndPointLatitude(orderInfoForm.getEndPointLatitude());
        newOrderDispatchVo.setExpectAmount(orderInfoForm.getExpectAmount());
        newOrderDispatchVo.setExpectDistance(orderInfoForm.getExpectDistance());
        newOrderDispatchVo.setExpectTime(drivingLineVo.getDuration());
        newOrderDispatchVo.setFavourFee(orderInfoForm.getFavourFee());
        newOrderDispatchVo.setCreateTime(new Date());
        //5.2.添加并执行任务调度
        Long jobId = newOrderFeignClient.addAndStartTask(newOrderDispatchVo).getData();
        log.info("订单id为： {}，绑定任务id为：{}", orderId, jobId);
        return orderId;
    }

    @Override
    public Integer getOrderStatus(Long orderId) {
        return orderInfoFeignClient.getOrderStatus(orderId).getData();
    }

    @Override
    public List<NewOrderDataVo> findNewOrderQueueData(Long driverId) {
        return newOrderFeignClient.findNewOrderQueueData(driverId).getData();
    }

    @Override
    public CurrentOrderInfoVo searchCustomerCurrentOrder(Long customerId) {
        Result<CurrentOrderInfoVo> currentOrderInfoVoResult = orderInfoFeignClient.searchCustomerCurrentOrder(customerId);
        if (currentOrderInfoVoResult.getCode()!=200){
            throw new GuiguException(ResultCodeEnum.SYSTEM_ERROR);
        }
        return currentOrderInfoVoResult.getData();
    }

    @Override
    public OrderInfoVo getOrderInfo(Long orderId, Long customerId) {
        //订单信息
        OrderInfo orderInfo = orderInfoFeignClient.getOrderInfo(orderId).getData();
        if (orderInfo.getCustomerId().longValue() != customerId.longValue()) {
            throw new GuiguException(ResultCodeEnum.ILLEGAL_REQUEST);
        }

        //获取司机信息
        DriverInfoVo driverInfoVo = null;
        if(null != orderInfo.getDriverId()) {
            driverInfoVo = driverInfoFeignClient.getDriverInfo(orderInfo.getDriverId()).getData();
        }

        //账单信息
        OrderBillVo orderBillVo = null;
        if (orderInfo.getStatus() >= OrderStatus.UNPAID.getCode()) {
            orderBillVo = orderInfoFeignClient.getOrderBillInfo(orderId).getData();
        }

        //封装订单信息
        OrderInfoVo orderInfoVo = new OrderInfoVo();
        orderInfoVo.setOrderId(orderId);
        BeanUtils.copyProperties(orderInfo, orderInfoVo);
        orderInfoVo.setOrderBillVo(orderBillVo);
        return orderInfoVo;
    }

    @Override
    public DriverInfoVo getDriverInfo(Long userId, Long orderId) {
        Result<OrderInfo> orderInfoResult = orderInfoFeignClient.getOrderInfo(orderId);
        if (orderInfoResult.getCode()!=200) {
            throw new GuiguException(ResultCodeEnum.SYSTEM_ERROR);
        }
        OrderInfo orderInfo = orderInfoResult.getData();
        Long driverId = orderInfo.getDriverId();
        Result<DriverInfoVo> driverInfoVoResult = driverInfoFeignClient.getDriverInfo(driverId);
        if (driverInfoVoResult.getCode() != 200) {
            throw new GuiguException(ResultCodeEnum.SYSTEM_ERROR);
        }
        return driverInfoVoResult.getData();
    }

    @Override
    public OrderLocationVo getCacheOrderLocation(Long orderId) {
        Result<OrderLocationVo> cacheOrderLocation = locationFeignClient.getCacheOrderLocation(orderId);
        if (cacheOrderLocation.getCode()!=200) {
            throw new GuiguException(ResultCodeEnum.SYSTEM_ERROR);
        }
        return cacheOrderLocation.getData();
    }

    @Override
    public DrivingLineVo calculateDrivingLine(CalculateDrivingLineForm calculateDrivingLineForm) {
        Result<DrivingLineVo> drivingLineVoResult = mapFeignClient.calculateDrivingLine(calculateDrivingLineForm);
        if (drivingLineVoResult.getCode()!=200) {
            throw new GuiguException(ResultCodeEnum.SYSTEM_ERROR);
        }
        return drivingLineVoResult.getData();
    }

    @Override
    public OrderServiceLastLocationVo getOrderServiceLastLocation(Long orderId) {
        Result<OrderServiceLastLocationVo> orderServiceLastLocationResult = locationFeignClient.getOrderServiceLastLocation(orderId);
        Integer code = orderServiceLastLocationResult.getCode();
        return orderServiceLastLocationResult.getData();
    }

    @Override
    public PageVo findCustomerOrderPage(Long customerId, Long page, Long limit) {
        return orderInfoFeignClient.findCustomerOrderPage(customerId, page, limit).getData();
    }

    @Override
    public WxPrepayVo createWxPayment(CreateWxPaymentForm createWxPaymentForm) {
        Long customerId = createWxPaymentForm.getCustomerId();
        //1.获取订单支付信息
        Result<OrderPayVo> orderPayVoResult = orderInfoFeignClient.getOrderPayVo(createWxPaymentForm.getOrderNo(), customerId);
        if (orderPayVoResult.getCode() != 200){
            throw new GuiguException(ResultCodeEnum.SYSTEM_ERROR);
        }
        OrderPayVo orderPayVo = orderPayVoResult.getData();
        //2.获取乘客和司机的openid
        Result<String> customerOpenId = customerInfoFeignClient.getCustomerOpenId(customerId);
        Result<String> driverOpenId = driverInfoFeignClient.getDriverOpenId(orderPayVo.getDriverId());
        //3.封装创建微信支付所需的参数
        PaymentInfoForm paymentInfoForm = new PaymentInfoForm();
        paymentInfoForm.setOrderNo(orderPayVo.getOrderNo());
        paymentInfoForm.setAmount(orderPayVo.getPayAmount());
        paymentInfoForm.setContent(orderPayVo.getContent());
        paymentInfoForm.setPayWay(1);
        paymentInfoForm.setContent(customerOpenId.getData());
        paymentInfoForm.setDriverOpenId(driverOpenId.getData());
        //4.创建微信支付
        Result<WxPrepayVo> wxPaymentResult = wxPayFeignClient.createWxPayment(paymentInfoForm);
        if (wxPaymentResult.getCode() != 200){
            throw new GuiguException(ResultCodeEnum.SYSTEM_ERROR);
        }
        return wxPaymentResult.getData();
    }

    @Override
    public Boolean queryPayStatus(String orderNo) {
        return wxPayFeignClient.queryPayStatus(orderNo).getData();
    }
}
